﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Collections.ObjectModel;

namespace конфигуратор
{
   

    public class ЭлементМассива : INotifyPropertyChanged
    {
        public ДинамикОбъект _динОбъект;
        public int индекс;
        public int Индекс { get { return индекс; } }
        
        public object Значение
        {
            get { return (( IList ) _динОбъект.Объект)[индекс]; }
            set
            {
                try
                {  
                     var новое= Парсер.Преобразовать( (string) value, _динОбъект.ТипЭлемента );
                     ((IList)_динОбъект.Объект)[индекс] = новое;
                }
                catch (Exception)
                {
                }
                Обновить();
                
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void Обновить ()
        {
            if ( PropertyChanged != null )
                PropertyChanged( this, new PropertyChangedEventArgs( "" ) );
        }

        public static  object ДатьЭлементыМассива ( ДинамикОбъект динобъект )
        {
            var массивЭлементов = new ObservableCollection<ЭлементМассива>();
            //var bbb = new Collection<ЭлементМассива>();
            if ( динобъект == null || динобъект.Объект == null ) return null;
            var список = динобъект.Объект as IList;
            if ( список!=null )
                for (int index = 0; index < список.Count; index++)
                {
                    массивЭлементов.Add(new ЭлементМассива() {индекс = index,  
                        _динОбъект = динобъект});
                }
            return массивЭлементов;
        }

    }



    public class ДинСписок :
        IList,
        INotifyCollectionChanged  
        //,  INotifyPropertyChanged
    {
        private ДинамикОбъект ДинОбъект;
        public IList Список;
        public static object ДатьСписок ( ДинамикОбъект динамикОбъект )
        {
            var список = динамикОбъект.Объект as IList;
            if ( список != null )
            {
                return new ДинСписок( динамикОбъект );
            }
            return null;

        }
        public ДинСписок () { }
        public ДинСписок ( ДинамикОбъект динамикОбъект )
        {
            ДинОбъект = динамикОбъект;
            Список = динамикОбъект.Объект as IList;
        }

        public Type ТипЭлемента
        {
            get
            {
                var тип = Список.GetType();
                if (тип.IsGenericType)
                {
                    return тип.GetGenericArguments()[0];
                }
                if (тип.IsArray)
                {
                    return тип.GetElementType();
                }
                return null;
            }
        }

        #region Члены INotifyCollectionChanged

        public event NotifyCollectionChangedEventHandler CollectionChanged;

        #endregion

        #region Члены INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;
        void Обновить( string свойство)
        {
            if ( PropertyChanged != null )
                PropertyChanged( this, new PropertyChangedEventArgs( свойство ) );
        }

        #endregion

        #region Члены IEnumerable

        IEnumerator IEnumerable.GetEnumerator ()
        {
            return new ЭлементНумератор( this );
        }

        #endregion

        #region Члены IList

        public int Add ( object value )
        {
            //if ( !this.IsFixedSize )
            //{
            //    var элемент = ( ЭлементМассива ) value;
            //    try
            //    {
            //        var значение = Парсер.Преобразовать( элемент.Строка, ТипЭлемента );
            //        элемент.индекс = Список.Add( значение );

            //        CollectionChanged( this, new NotifyCollectionChangedEventArgs(
            //              NotifyCollectionChangedAction.Add, элемент, элемент.индекс ) );
            //        Обновить( "Count" );
            //        return элемент.индекс;
            //    }
            //    catch ( Exception )
            //    {

            //        //throw;
            //    }




            //    //if (элемент.ЗначениеЭлемента!=null)
            //    //return   Список.Add( ( (ЭлементМассива) value).ЗначениеЭлемента );

            //    var val = ТипЭлемента.IsValueType;

            //    var ctors = ТипЭлемента.GetConstructors( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance );
            //    if ( ctors.Length != 0 )
            //    {
            //        var el = ctors[0].Invoke( null );
            //        var num = Список.Add( el );
            //        CollectionChanged( this, new NotifyCollectionChangedEventArgs(
            //            NotifyCollectionChangedAction.Add, el, num ) );
            //        Обновить( "Count" );
            //        return num;
            //    }

            //}
            return -1;
        }

        public bool Contains ( object value )
        {
            //if ( value != null && value is ЭлементМассива )
            return Список.Contains(((ЭлементМассива)value).Значение);

        }

        public void Clear()
        {
            Список.Clear();
        }

        public int IndexOf ( object value )
        {
            //if (value!=null && value is ЭлементМассива)
            return Список.IndexOf(((ЭлементМассива)value).Значение);   
        }

        public void Insert ( int index, object value )
        {
            throw new NotImplementedException();
        }

        public bool IsReadOnly
        {
            get { return Список.IsReadOnly; }
        }

        public bool IsFixedSize
        {
            get { return Список.IsFixedSize; }
        }

        public void Remove ( object value )
        {
            throw new NotImplementedException();
        }

        public void RemoveAt(int index)
        {
            throw new NotImplementedException();
        }

        public object this[int index]
        {
            get
            {
                return new ЭлементМассива
                {
                    индекс = index,
                    //ЗначениеЭлемента = Список[index],
                    _динОбъект = ДинОбъект
                };
            }
            set
            {
                var oldItem = Список[index];

                Список[index] = (( ЭлементМассива ) value).Значение;

                CollectionChanged( this, new NotifyCollectionChangedEventArgs(
                    NotifyCollectionChangedAction.Replace, Список[index], oldItem, index ) );
            }
        }

        #endregion

        #region Члены ICollection

        public void CopyTo ( Array array, int index )
        {
            int num = index;
            var arr = array as object[];
            var count = Список.Count;
            for (var ind = 0; ind < count; ind++)
            {
                arr[num++] = Список[ind];
            }

        }

        public int Count
        {
            get { return Список.Count; }
        }

        public bool IsSynchronized
        {
            get { return Список.IsSynchronized; }
        }

        public object SyncRoot
        {
            get { return Список.SyncRoot; }
        }

        #endregion

       
    }

    public class ЭлементНумератор : IEnumerator
    {
        private ДинСписок _динСписок;
        private int index = -1;
        private ЭлементМассива элементМассива;
        public ЭлементНумератор ( ДинСписок динСписок )
        {
            _динСписок = динСписок;
            элементМассива = default( ЭлементМассива );
        }

        #region Члены IDisposable

        public void Dispose ()
        {

        }

        #endregion


        object IEnumerator.Current
        {
            get { return элементМассива; }
        }

        public bool MoveNext ()
        {
            if ( ++index >= _динСписок.Count ) return false;
            else
            {
                элементМассива = (ЭлементМассива) ((IList)_динСписок)[index];
                return true;
            }
        }

        public void Reset ()
        {
            index = -1;
        }

    }
}
